home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / machack / Hacks96 / FinderUndo.sit / Finder Undo / main.c < prev    next >
C/C++ Source or Header  |  1996-06-22  |  12KB  |  657 lines

  1. #include <A4Stuff.h>
  2. #include "main.h"
  3. #include "patches.h"
  4.  
  5.  
  6. ///////////////////////////////////////////////////////////
  7.  
  8.  
  9. InitGrafProc        oldInitGraf = nil;
  10. Pack8Proc            oldPack8 = nil;
  11. MenuSelectProc        oldMenuSelect = nil;
  12. MenuKeyProc            oldMenuKey = nil;
  13. SpecialHandlerProc    shpChainProc = nil;
  14.  
  15. Boolean                igpatched = false;
  16. NMRecPtr            myNotification = nil;
  17.  
  18. Boolean            inAESend = false;
  19.  
  20. OSType            lastAction = 0;
  21. Handle            lastActionHero = nil;
  22. enum {
  23.     kCleanUpEvent    = 1,
  24.     kOpenEvent,
  25.     kCloseEvent,
  26.     kSelectEvent
  27. };
  28.  
  29. ///////////////////////////////////////////////////////////
  30.  
  31.  
  32. void main(void)
  33. {
  34.     Handle    me;
  35.     
  36.     EnterCodeResource();
  37.     
  38.     me = Get1Resource( 'INIT', 128 );
  39.     HLock(me);
  40.     DetachResource(me);
  41.     
  42.     PatchInitGraf();
  43.     
  44.     ExitCodeResource();
  45. }
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53. inline void pstrcat( StringPtr s1, StringPtr s2 )
  54. {
  55.     BlockMoveData( s2+1, s1+s1[0]+1, s2[0] );
  56.     s1[0] += s2[0];
  57. }
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67. pascal long MyMenuSelect( Point startPt )
  68. {
  69.     long        happy;
  70.     
  71.     EnterCodeResource();
  72.     
  73.     if (lastAction)
  74.         EnableItem( GetMenuHandle(0x0102), 1 );
  75.     else
  76.         DisableItem( GetMenuHandle(0x0102), 1 );
  77.     
  78.     happy = (*oldMenuSelect)( startPt );
  79.     if (happy == 0x01020001)
  80.     {
  81.         UndoLastAction();
  82.         lastAction = 0;
  83.         if (lastActionHero) DisposeHandle( lastActionHero );
  84.         happy = 0;
  85.     }
  86.     
  87. skip:
  88.     ExitCodeResource();
  89.     return happy;
  90. }
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113. pascal long MyMenuKey( short ch )
  114. {
  115.     long            happy;
  116.     
  117.     EnterCodeResource();
  118.     
  119.     if (lastAction)
  120.         EnableItem( GetMenuHandle(0x0102), 1 );
  121.     else
  122.         DisableItem( GetMenuHandle(0x0102), 1 );
  123.     
  124.     happy = (*oldMenuKey)( ch );
  125.     
  126.     if ( happy == 0x01020001 )        // edit:undo -- yep, hardcoded!!
  127.     {
  128.         UndoLastAction();
  129.         lastAction = 0;
  130.         if (lastActionHero) DisposeHandle( lastActionHero );
  131.         happy = 0;
  132.     }
  133.     
  134. skip:
  135.     ExitCodeResource();
  136.     return happy;
  137. }
  138.  
  139.  
  140.  
  141.  
  142.  
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149.  
  150.  
  151.  
  152. void InstallBlankNotification( void )
  153. {
  154.     NMRecPtr myNotification = (NMRecPtr) NewPtrSysClear( sizeof(NMRec));
  155.     myNotification->qLink = 0;
  156.     myNotification->qType = nmType;
  157.     myNotification->nmMark = 0;
  158.     myNotification->nmIcon = nil;
  159.     myNotification->nmSound = nil;
  160.     myNotification->nmStr = nil;
  161.     myNotification->nmResp = CustomNMRemove;
  162.     myNotification->nmRefCon = 0;
  163.     
  164.     NMInstall(myNotification);
  165. }
  166.  
  167.  
  168.  
  169.  
  170. pascal void CustomNMRemove( NMRecPtr nmr )
  171. {
  172.     EnterCodeResource();
  173.  
  174.     NMRemove( nmr );
  175.     DisposePtr( (Ptr)nmr );
  176.     
  177.     
  178.     // tell the finder that it's about to start recording itself :>
  179.     {
  180.         AppleEvent            recEvt = {typeNull,nil}, reply = {typeNull,nil};
  181.         ProcessSerialNumber    finderPSN = { 0, kCurrentProcess };
  182.         AEDesc                target = {typeNull,nil}, finderDesc = {typeNull,nil};
  183.         
  184.         GetCurrentProcess( &finderPSN );
  185.         AECreateDesc( typeProcessSerialNumber, &finderPSN, sizeof(ProcessSerialNumber), &target );
  186.         AECreateAppleEvent( 'core', 'rec1', &target, kAutoGenerateReturnID, 0, &recEvt);
  187.         AEPutAttributeDesc( &recEvt, keyOriginalAddressAttr, &target );
  188.         AESend( &recEvt, &reply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, nil, nil);
  189.         
  190.         AEDisposeDesc( &target );
  191.         AEDisposeDesc( &finderDesc );
  192.         AEDisposeDesc( &recEvt );
  193.         AEDisposeDesc( &reply );
  194.  
  195.     }
  196.     
  197.     ExitCodeResource();
  198. }
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214. void InstallAEHooks( void )
  215. {
  216.     AEGetSpecialHandler( keyPreDispatch, (UniversalProcPtr*)&shpChainProc, false );
  217.     AEInstallSpecialHandler( keyPreDispatch, (UniversalProcPtr)MySpecialHandler, false );
  218. }
  219.  
  220.  
  221.  
  222.  
  223.  
  224.  
  225. pascal OSErr MySpecialHandler( const AppleEvent *theAppleEvent,
  226.                     const AppleEvent *reply, long handlerRefcon )
  227. {
  228.     SpecialHandlerProc    localSHP;
  229.     EnterCodeResource();
  230.     
  231.     if ( CAPS_KEY_IS_DOWN )
  232.         DisplayAEVT( theAppleEvent );
  233.     
  234.     localSHP = shpChainProc;
  235.     ExitCodeResource();
  236.     if (localSHP)
  237.         return (*localSHP) (theAppleEvent, reply, handlerRefcon);
  238.     else
  239.         return errAEEventNotHandled;
  240. }
  241.  
  242.  
  243.  
  244.  
  245.  
  246.  
  247.  
  248.  
  249.  
  250. OSErr MyAESend (const AppleEvent *theAppleEvent, AppleEvent *reply,
  251.      AESendMode sendMode, AESendPriority sendPriority,
  252.      long timeOutInTicks, UniversalProcPtr idleProc,
  253.      UniversalProcPtr filterProc)
  254. {
  255.     AEKeyword    junkkey, evClass, evID;
  256.     Size        junksize;
  257.     
  258.     EnterCodeResource();
  259.     
  260.     if (inAESend) goto skip;
  261.     inAESend = true;
  262.  
  263.  
  264.  
  265.     if (CAPS_KEY_IS_DOWN)
  266.         DisplayAEVT( theAppleEvent );
  267.  
  268.  
  269.  
  270.     // grab the event class and id
  271.     AEGetAttributePtr( theAppleEvent, keyEventClassAttr, typeWildCard, &junkkey, &evClass, sizeof(evClass), &junksize );
  272.     AEGetAttributePtr( theAppleEvent, keyEventIDAttr, typeWildCard, &junkkey, &evID, sizeof(evID), &junksize );
  273.     
  274.     switch( evClass )
  275.     {
  276.         case 'fndr':
  277.             switch (evID)
  278.             {
  279.                 case 'fclu':
  280.                     lastAction = kCleanUpEvent;
  281.                     if (lastActionHero) DisposeHandle(lastActionHero);
  282.                     lastActionHero = nil;
  283.                     RememberCleanup();
  284.                     break;
  285.             }
  286.             break;
  287.         
  288.         case 'core':
  289.             switch (evID)
  290.             {
  291.                 case 'clos':
  292.                     lastAction = kCloseEvent;
  293.                     if (lastActionHero) DisposeHandle(lastActionHero);
  294.                     lastActionHero = nil;
  295.                     RememberClose( theAppleEvent );
  296.                     break;
  297.             }
  298.             break;
  299.             
  300. /*        case 'aevt':
  301.             switch (evID)
  302.             {
  303.                 case 'odoc':
  304.                     RememberOpen( theAppleEvent );
  305.                     break;
  306.             }
  307.             break;
  308.             
  309.         case 'misc':
  310.             switch (evID)
  311.             {
  312.                 case 'slct':
  313.                     if (lastActionHero) DisposeHandle(lastActionHero);
  314.                     lastActionHero = nil;
  315.                     RememberSelect( theAppleEvent );
  316.                     break;
  317.             }
  318.             break;
  319. */
  320.     }
  321.     
  322.     inAESend = false;
  323.     
  324. skip:
  325.     ExitCodeResource();
  326. }
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336. void RememberCleanup( void )
  337. {
  338.     short        volindex = 0, fileindex;
  339.     FSSpec        spec;
  340.     CInfoPBRec    pb;
  341.     Ptr            lap;
  342.     
  343.     AppleEvent            moveEvt = {typeNull,nil}, reply = {typeNull,nil};
  344.     ProcessSerialNumber    finderPSN = { 0, kCurrentProcess };
  345.     AEDesc                target = {typeNull,nil}, finderDesc = {typeNull,nil};
  346.     EventRecord        ev;
  347.     
  348.     GetCurrentProcess( &finderPSN );
  349.     AECreateDesc( typeProcessSerialNumber, &finderPSN, sizeof(ProcessSerialNumber), &target );
  350.     lastActionHero = NewHandleSys( 32768 );
  351.     HLock(lastActionHero);
  352.     lap = *lastActionHero;
  353.     
  354.     while ( (spec.vRefNum = GetIndVolume(++volindex)) != 0 )
  355.     {
  356.         long    saveDirID;
  357.         
  358.         FlushVol( nil, spec.vRefNum );
  359.         
  360.         spec.name[0] = 0;
  361.         pstrcat( spec.name, "\pDesktop Folder" );
  362.         spec.parID = 2;
  363.         
  364.         if (FSpGetCatInfo( &spec, &pb, 0 ))
  365.             continue;
  366.         
  367.         saveDirID = spec.parID = pb.dirInfo.ioDrDirID;
  368.         
  369.         fileindex = 0;
  370.         while ( !FSpGetCatInfo( &spec, &pb, ++fileindex ) )
  371.         {
  372.             AEDesc    object, object2, where;
  373.             Point    point;
  374.             
  375.             *(FSSpec*)lap = spec;
  376.             lap += sizeof(FSSpec);
  377.             
  378.             pb.hFileInfo.ioFlFndrInfo.fdLocation.v += LMGetMBarHeight();
  379.             point = *(Point*)lap = pb.hFileInfo.ioFlFndrInfo.fdLocation;
  380.             lap += sizeof(Point);
  381.             
  382.             spec.parID = saveDirID;
  383.         }
  384.     }
  385.     
  386.     SetHandleSize( lastActionHero, lap - *lastActionHero );
  387.     HNoPurge( lastActionHero );
  388.     HUnlock( lastActionHero );
  389. }
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399. void UndoCleanup( void )
  400. {
  401.     Ptr        lap;
  402.     Size    hsize = GetHandleSize( lastActionHero );
  403.     FSSpec    spec;
  404.     Point    point;
  405.  
  406.     AppleEvent            moveEvt = {typeNull,nil}, reply = {typeNull,nil};
  407.     ProcessSerialNumber    finderPSN = { 0, kCurrentProcess };
  408.     AEDesc                target = {typeNull,nil}, finderDesc = {typeNull,nil};
  409.     EventRecord        ev;
  410.     
  411.     GetCurrentProcess( &finderPSN );
  412.     AECreateDesc( typeProcessSerialNumber, &finderPSN, sizeof(ProcessSerialNumber), &target );
  413.     
  414.     HLock( lastActionHero );
  415.     lap = *lastActionHero;
  416.     
  417.     while ( lap < hsize + *lastActionHero )
  418.     {
  419.         AEDesc    fss, item, propobj, nullobj = {typeNull,nil};
  420.         AEDesc    where, property;
  421.         OSType    prop = 'posn';
  422.         
  423.         spec = *(FSSpec*)lap;
  424.         lap += sizeof(FSSpec);
  425.         
  426.         point = *(Point*)lap;
  427.         lap += sizeof(Point);
  428.         
  429.         AECreateDesc( typeFSS, &spec, sizeof(spec), &fss );
  430.         AECreateDesc( 'QDpt', &point, sizeof(Point), &where );
  431.         AECreateDesc( typeType, &prop, sizeof(prop), &property );
  432.         
  433.         // given an fsspec, make an object that means "this item"
  434.         AECoerceDesc( &fss, 'obj ', &item );
  435.         *(long*)(*item.dataHandle + 20) = 'citm';    // from 'file' to 'citm'...
  436.         
  437.         // now make an object that means "this property of this item"
  438.         CreateObjSpecifier( 'prop', &item, formPropertyID, &property, false, &propobj );
  439.         
  440.         // lastly create and send the set-data event
  441.         AECreateAppleEvent( 'core', 'setd', &target, kAutoGenerateReturnID, 0, &moveEvt );
  442.         AEPutParamDesc( &moveEvt, '----', &propobj );
  443.         AEPutParamDesc( &moveEvt, 'data', &where );
  444.         
  445.         AESend( &moveEvt, &reply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, nil, nil);
  446.         while (EventAvail( highLevelEventMask, &ev))
  447.         {
  448.             WaitNextEvent( highLevelEventMask, &ev, 0, nil );
  449.             if (AEProcessAppleEvent( &ev ))
  450.                 DebugStr( "\perror processing the event;error d0.w" );
  451.         }
  452.         
  453.         AEDisposeDesc( &fss );
  454.         AEDisposeDesc( &item );
  455.         AEDisposeDesc( &propobj );
  456.         AEDisposeDesc( &where );
  457.         AEDisposeDesc( &moveEvt );
  458.         AEDisposeDesc( &reply );
  459.         AEDisposeDesc( &property );
  460.     }
  461.     
  462.     AEDisposeDesc( &target );
  463.     AEDisposeDesc( &finderDesc );
  464.     AEDisposeDesc( &moveEvt );
  465.     AEDisposeDesc( &reply );
  466. }
  467.  
  468.  
  469.  
  470.  
  471. void RememberClose( const AppleEvent *evt )
  472. {
  473.     AppleEvent    open;
  474.     OSType        newClass = 'aevt', newID = 'odoc';
  475.     
  476.     lastAction = kCloseEvent;
  477.     lastActionHero = evt->dataHandle;
  478.     HandToHand( &lastActionHero );
  479.     
  480.     // modify the handle so it looks like an open event
  481.     open.descriptorType = 'aevt';
  482.     open.dataHandle = lastActionHero;
  483.     
  484.     AEPutAttributePtr( &open, keyEventClassAttr, typeType, &newClass, sizeof(OSType) );
  485.     AEPutAttributePtr( &open, keyEventIDAttr, typeType, &newID, sizeof(OSType) );
  486.     
  487.     // no AEDisposeDesc, please!! we need the handle!
  488. }
  489.  
  490.  
  491. void UndoClose( void )
  492. {
  493.     AppleEvent    open, reply = {typeNull,nil};
  494.     EventRecord    ev;
  495.     
  496.     open.descriptorType = 'aevt';
  497.     open.dataHandle = lastActionHero;
  498.     
  499.     AESend( &open, &reply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, nil, nil);
  500.     while (EventAvail( highLevelEventMask, &ev))
  501.     {
  502.         WaitNextEvent( highLevelEventMask, &ev, 0, nil );
  503.         if (AEProcessAppleEvent( &ev ))
  504.             DebugStr( "\perror processing the event;error d0.w" );
  505.     }
  506.     
  507.     AEDisposeDesc( &open );
  508.     AEDisposeDesc( &reply );
  509.     lastActionHero = nil;
  510.     lastAction = 0;
  511. }
  512.  
  513.  
  514.  
  515. void RememberSelect( const AppleEvent *evt )
  516. {
  517.     lastAction = kSelectEvent;
  518.     lastActionHero = evt->dataHandle;
  519.     HandToHand( &lastActionHero );
  520. }
  521.  
  522.  
  523.  
  524.  
  525.  
  526. void RememberOpen( const AppleEvent *evt )
  527. {
  528.     AppleEvent    close = {'aevt',nil};
  529.     OSType        newClass = 'core', newID = 'clos';
  530.     
  531.     if (lastAction == kSelectEvent && lastActionHero)
  532.     {
  533.         close.dataHandle = lastActionHero;
  534.     }
  535.     else
  536.     {
  537.         if (lastActionHero) DisposeHandle(lastActionHero);
  538.         close.dataHandle = evt->dataHandle;
  539.         HandToHand( &close.dataHandle );
  540.     }
  541.     
  542.     AEPutAttributePtr( &close, keyEventClassAttr, typeType, &newClass, sizeof(OSType) );
  543.     AEPutAttributePtr( &close, keyEventIDAttr, typeType, &newID, sizeof(OSType) );
  544.     lastAction = kOpenEvent;
  545.     lastActionHero = close.dataHandle;
  546. }
  547.  
  548.  
  549.  
  550. void UndoOpen( void )
  551. {
  552.     AppleEvent    close = {'aevt',nil}, reply = {typeNull,nil};
  553.     EventRecord    ev;
  554.     
  555.     close.dataHandle = lastActionHero;
  556.     
  557.     if (CAPS_KEY_IS_DOWN)
  558.         DisplayAEVT( &close );
  559.     
  560.     AESend( &close, &reply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, nil, nil);
  561.     while (EventAvail( highLevelEventMask, &ev))
  562.     {
  563.         WaitNextEvent( highLevelEventMask, &ev, 0, nil );
  564.         if (AEProcessAppleEvent( &ev ))
  565.             DebugStr( "\perror processing the event;error d0.w" );
  566.     }
  567.     
  568.     AEDisposeDesc( &close );
  569.     AEDisposeDesc( &reply );
  570.     lastActionHero = nil;
  571.     lastAction = 0;
  572. }
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582. OSErr FSpGetCatInfo( FSSpec *spec, CInfoPBPtr pb, short index )
  583. {
  584.     OSErr    err;
  585.     
  586.     pb->dirInfo.ioFVersNum        = 0;
  587.     pb->dirInfo.ioCompletion    = nil;
  588.     pb->dirInfo.ioNamePtr        = spec->name;
  589.     pb->dirInfo.ioVRefNum        = spec->vRefNum;
  590.     pb->dirInfo.ioFDirIndex        = index;
  591.     pb->dirInfo.ioDrDirID        = spec->parID;
  592.     
  593.     err = PBGetCatInfoSync(pb);
  594.     
  595.     // these fields are at the same offset for both dirInfo and hFileInfo.
  596.     spec->vRefNum = pb->dirInfo.ioVRefNum;
  597.     spec->parID = pb->dirInfo.ioDrParID;
  598.     
  599.     return err;
  600. }
  601.  
  602.  
  603.  
  604.  
  605.  
  606.  
  607. short GetIndVolume( short index )
  608. {
  609.     QHdrPtr        vcbq = GetVCBQHdr();
  610.     VCB    *volp = (VCB*)(vcbq->qHead);
  611.     
  612.     while (volp && --index)
  613.         volp = (VCB*)volp->qLink;
  614.     
  615.     if (volp) return volp->vcbVRefNum;
  616.     else      return 0;
  617. }
  618.  
  619.  
  620.  
  621.  
  622.  
  623.  
  624. void UndoLastAction( void )
  625. {
  626.     if (!lastActionHero) return;
  627.     
  628.     switch (lastAction)
  629.     {
  630.         case kCleanUpEvent:
  631.             UndoCleanup();
  632.             break;
  633.         
  634.         case kCloseEvent:
  635.             UndoClose();
  636.             break;
  637.         
  638.         case kOpenEvent:
  639.             //UndoOpen();
  640.             break;
  641.         
  642.     }
  643. }
  644.  
  645.  
  646.  
  647. void DisplayAEVT( const AppleEvent *evt )
  648. {
  649.     Str255    s,n;
  650.     *s = 0;
  651.     NumToString((long)evt,n);
  652.     pstrcat(s,"\p;aevt #");
  653.     pstrcat(s,n);
  654.     DebugStr(s);
  655. }
  656.  
  657.